package io.zim.modules.ws.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.zim.common.utils.StringUtil;
import io.zim.modules.back.entity.SysApplyEntity;
import io.zim.modules.back.service.SysApplyService;
import io.zim.modules.ws.config.ShowcaseServerConfig;
import io.zim.modules.ws.entity.IdentityEntity;
import io.zim.modules.ws.handler.HandlerFactory;
import io.zim.modules.ws.handler.WsMsgHandler;
import io.zim.modules.ws.utils.BeanValidator;
import io.zim.modules.ws.utils.TransitionUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.tio.core.ChannelContext;
import org.tio.core.Tio;
import org.tio.http.common.HttpRequest;
import org.tio.http.common.HttpResponse;
import org.tio.http.common.HttpResponseStatus;
import org.tio.websocket.common.WsRequest;
import org.tio.websocket.common.WsResponse;
import org.tio.websocket.server.handler.IWsMsgHandler;

import javax.annotation.PostConstruct;
import java.util.Map;

/**
 *
 * @author
 * @since
 */
@Component
public class ShowcaseWsMsgHandler implements IWsMsgHandler {
  private static Logger log = LoggerFactory.getLogger(ShowcaseWsMsgHandler.class);

  public static final ShowcaseWsMsgHandler me = new ShowcaseWsMsgHandler();

  @Autowired
  private SysApplyService sysApplyService;

  public static ShowcaseWsMsgHandler showcaseWsMsgHandler;

  private ShowcaseWsMsgHandler() {

  }

  @PostConstruct
  public void init(){
    showcaseWsMsgHandler = this;
    showcaseWsMsgHandler.sysApplyService = this.sysApplyService;
  }

  /**
   * 握手时走这个方法，业务可以在这里获取cookie，request参数等
   */
  @Override
  public HttpResponse handshake(HttpRequest request, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
    Map params = request.getParams();
    IdentityEntity identityEntity = (IdentityEntity) TransitionUtils.mapToObject(params,IdentityEntity.class);
    String userId = identityEntity.getAppKey() + "." + identityEntity.getUserId();
    //验证身份
    try {
      BeanValidator.validate(identityEntity);
      SysApplyEntity applyEntity = showcaseWsMsgHandler.sysApplyService.getOne(
          new QueryWrapper<SysApplyEntity>().eq("app_key",identityEntity.getAppKey())
      );
      String signature = DigestUtils.sha1Hex(applyEntity.getAppSecret() + identityEntity.getNonce() + identityEntity.getSignTimestamp());
      if ( !identityEntity.getSignature().equalsIgnoreCase(signature) ) {
        log.info(signature + "======" + identityEntity.getSignature());
        httpResponse.setStatus(HttpResponseStatus.C401);
        return httpResponse;
      }
    } catch (Exception e) {
      httpResponse.setStatus(HttpResponseStatus.C401);
      httpResponse.setBody(e.getMessage().getBytes());
      return httpResponse;
    }
    //绑定用户//channelContext.setUserid(myname);
    if (identityEntity.getIdentity().equalsIgnoreCase("service")) {
      Tio.bindUser(channelContext, userId + ".service");
      Tio.bindGroup(channelContext, identityEntity.getAppKey() + ".service");
    } else if (identityEntity.getIdentity().equalsIgnoreCase("user")) {
      Tio.bindUser(channelContext, userId);
      Tio.bindGroup(channelContext, identityEntity.getAppKey());
    }
    //绑定组
    if (!StringUtil.isNullOrEmpty(identityEntity.getGroups())) {
      String[] groups = identityEntity.getGroups().split(",");
      int amount = 100;
      amount = groups.length <= amount ? groups.length : amount;
      for (int i = 0; i < amount; i++) {
        Tio.bindGroup(channelContext, identityEntity.getAppKey() + "." + groups[i]);
      }
    }
/*  String clientip = request.getClientIp();
    log.info("收到来自{}的ws握手包\r\n{}", clientip, request.toString());*/
    return httpResponse;
  }

  /**
   * 握手完成后执行此方法
   * @param httpRequest
   * @param httpResponse
   * @param channelContext
   * @throws Exception
   * @author tanyaowu
   */
  @Override
  public void onAfterHandshaked(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
/*    Map params = httpRequest.getParams();
    IdentityEntity identityEntity = (IdentityEntity) TransitionUtils.mapToObject(params,IdentityEntity.class);
    String userId = identityEntity.getAppKey() + "." + identityEntity.getUserId();

    String[] groups = identityEntity.getGroups().split(",");
    int count = Tio.getAllChannelContexts(channelContext.groupContext).getObj().size();
    String msg = "{name:'admin',message:'" + channelContext.userid + " 进来了，共【" + count + "】人在线" + "'}";
    //用tio-websocket，服务器发送到客户端的Packet都是WsResponse
    WsResponse wsResponse = WsResponse.fromText(msg, ShowcaseServerConfig.CHARSET);
    //群发
    log.info("onAfterHandshaked：{}响应\r\n{}", channelContext, httpResponse.toString());
    Tio.sendToGroup(channelContext.groupContext, identityEntity.getAppKey() + "." + groups[groups.length - 1], wsResponse);
    */
    //log.info("是否绑定user:{}",channelContext.userid);
  }

  /**
   * 字节消息（binaryType = arraybuffer）过来后会走这个方法
   */
  @Override
  public Object onBytes(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
    return null;
  }

  /**
   * 当客户端发close flag时，会走这个方法
   */
  @Override
  public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
    Tio.remove(channelContext, "receive close flag");
    return null;
  }

  /*
   * 字符消息（binaryType = blob）过来后会走这个方法
   */
  @Override
  public Object onText(WsRequest wsRequest, String text, ChannelContext channelContext) throws Exception {
    WsMsgHandler wsMsgHandler = HandlerFactory.createHandler(wsRequest,text,channelContext);
    return wsMsgHandler.handle();
/*
    WsSessionContext wsSessionContext = (WsSessionContext) channelContext.getAttribute();
    HttpRequest httpRequest = wsSessionContext.getHandshakeRequest();//获取websocket握手包
    if (log.isDebugEnabled()) {
      log.debug("握手包:{}", httpRequest);
    }

    log.info("收到ws消息:{}", text);
    String msg2 = "{name:'" + channelContext.userid + "',message:'" + text + "'}";
    Tio.sendToUser(channelContext.groupContext,"zzh517519",WsResponse.fromText(msg2, ShowcaseServerConfig.CHARSET));
    if (Objects.equals("心跳内容", text)) {
      return "心跳内容";
    }
    //channelContext.getToken()
    //String msg = channelContext.getClientNode().toString() + " 说：" + text;
    String msg = "{name:'" + channelContext.userid + "',message:'" + text + "'}";
    //用tio-websocket，服务器发送到客户端的Packet都是WsResponse
    WsResponse wsResponse = WsResponse.fromText(msg, ShowcaseServerConfig.CHARSET);
    //群发
    Tio.sendToGroup(channelContext.groupContext, Const.GROUP_ID, wsResponse);


    //返回值是要发送给客户端的内容，一般都是返回null
    return null;
    */
  }

}

